package vivace.view;


import java.util.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.util.Observer;
import java.util.Observable;
import javax.sound.midi.*;
import java.awt.*;
import vivace.helper.GUIHelper;
import vivace.helper.GridHelper;
import vivace.helper.ProjectHelper;
import vivace.model.Project;

import javax.swing.*;

public class PianoRoll extends JPanel implements Observer{

	private Project model;
	private Track track;
	private GridHelper gridHelper;
	
	//CONTAIN???	//CONTAIN???	//CONTAIN??? - THE VARIABLES FOR THE PAINTCOMPONENT
	int		currEvent;
	int		countNumber;
	int		pixelBig;
	int		lengthQuartInPixel;
	int		lengthOfLineX;
	
	double	pixelSmall;
	double	pixelSmallSpace;
	double	ticksPerCurrQuarter;
	double	ticksCounter;
	double 	ticksPerQuarter;
	
	int[][] timeSignature;
	//CONTAIN???	//CONTAIN???	//CONTAIN??? - THE VARIABLES FOR THE PAINTCOMPONENT
	

	public PianoRoll(Project model) {
		super(null); // Absolute positioning
		this.model = model;
		this.model.addObserver(this);
		this.setBackground(Color.WHITE);
		this.gridHelper = new GridHelper(this.model,GridHelper.Type.PIANOROLL);
		this.setPreferredSize(new Dimension(gridHelper.getWidth(),gridHelper.getHeight()));
	
		
	}
	
	/**
	 * paintComponent - everything to be drawn in the timeline is conctructed here
	 */
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		gridHelper.paintGrid(g);
	}
	
	// Removes all notes and repaints them
	private void repaintNotes(){
		
		this.track = this.model.getSelectedTrack();
		this.removeAll();
		
		if( this.track == null ) // Do nothing if no track is selected
			return;
		
		Vector<MidiEvent> es = ProjectHelper.allShortMessages(this.track);
		ShortMessage sm;
		long tmp[] = new long[128];
		for( MidiEvent e : es ){
			sm = (ShortMessage) e.getMessage();
			if( sm.getCommand() == 144 && sm.getData2() > 0 ){
				// A note was pressed, register the tick when this happened
				tmp[ sm.getData1() ] = e.getTick();
			} else if (sm.getCommand() == 128 || (sm.getCommand() == 144 && sm.getData2() == 0)){
				// A note was released, extract the time when the corresponding note was 
				// pressed and calculate the length of the note.
				int xStart = gridHelper.tickToXPosition(tmp[ sm.getData1() ]);
				int xEnd = gridHelper.tickToXPosition(e.getTick());
				int y = gridHelper.noteToYPosition(sm.getData1());
				EventBar b = new EventBar( ProjectHelper.getNoteName(sm.getData1(), true) );
				b.setWidth(xEnd - xStart);
				b.setPosition(xStart, y);
				this.add(b);
			}
			
		}
	}
	
	@Override
	public void update(Observable o,Object arg) { 

		// Check which type of action that was performed
    	Project.Action action = this.model.getAction();
    	
		// Then perform the desired updates depending on the action
    	switch( action ){
    	
    		case SELECTED_TRACK_CHANGED:
    		case ZOOMLEVEL_CHANGED:
    			repaintNotes();
    			this.setPreferredSize(new Dimension(gridHelper.getWidth(),gridHelper.getHeight()));
    			break;
    	}


		
		// Repaint the graphics 
		repaint();
		
	} 
	
}
